<template>
  <div class="users-container">
    <!-- 面包屑导航 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>用户管理</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片视图区 -->
    <el-card>
      <!-- gutter作用：使每栏之间间隔为20 -->
      <!-- layout布局区域 -->
      <el-row :gutter="20">
        <!-- 搜索框区域-->
        <!-- span的作用：每一行分为24份 此处占12份 -->
        <el-col :span="12">
          <!-- clearable为输入框添加的清空文本功能 clear事件在文本被清空是触发 -->
            <el-input placeholder="请输入搜索内容" v-model="queryInfo.query" clearable @clear="getUsersList">
              <el-button slot="append" icon="el-icon-search" @click="getUsersList"></el-button>
            </el-input>
        </el-col>
        <!-- 添加按钮区域 -->
        <el-col :span="6 ">
          <!-- 单击按钮并弹出对话框 -->
          <el-button type="primary" @click="dialogVisible = true">添加用户</el-button>
        </el-col>
      </el-row>
      <!-- 表格区域 -->
      <el-table
        :data="usersList"
        border
        stripe
        style="width: 100%">
        <!-- border为表格开启边框 stripe为表格开启斑马条纹 -->
        <!-- prop为该列绑定内容 内容为usersList中的数据 -->
        <!-- type="index"设置该列为索引列 -->
        <el-table-column
          type="index"
          label="#"
          width="50">
        </el-table-column>
        <el-table-column
          prop="username"
          label="姓名"
          width="80">
        </el-table-column>
        <el-table-column
          prop="email"
          label="邮箱"
          width="180">
        </el-table-column>
        <el-table-column
          prop="mobile"
          label="电话"
          width="180">
        </el-table-column>
        <el-table-column
          prop="role_name"
          label="角色"
          width="120">
        </el-table-column>
        <el-table-column
          prop="mg_state"
          label="状态">
          <!-- slot-scope：作用域插槽 scope接受了父类组件的数据usersList scope.row调用了所处行的数据 -->
          <template slot-scope="scope">
            <el-switch
              v-model="scope.row.mg_state"
              active-color="#13ce66"
              @change="userStateChange(scope.row)">
              <!-- 这里形参传入用户对象 在方法的内部要使用用户的id -->
              <!-- 因为此处双向绑定了vue组件中的用户数据但并未对服务器中的数据进行修改于是刷新页面后数据会复原 -->
            </el-switch>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          width="180">
          <!-- 若要在element表格中插入内容必须要先引用作用域插槽slot-scope -->
          <template slot-scope="scope">
            <el-tooltip class="item" effect="dark" content="修改角色" placement="top" :enterable="false">
              <el-button type="primary" icon="el-icon-edit" size="mini" @click="editDialog(scope.row.id)"></el-button>
            </el-tooltip>
            <el-tooltip class="item" effect="dark" content="删除角色" placement="top" :enterable="false">
              <el-button type="warning" icon="el-icon-delete" size="mini" @click="open(scope.row.id)"></el-button>
            </el-tooltip>
            <el-tooltip class="item" effect="dark" content="分配角色" placement="top" :enterable="false">
              <el-button type="danger" icon="el-icon-setting" size="mini" @click="setRoles(scope.row)"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页区域 -->
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="queryInfo.pagenum"
        :page-sizes="[1, 2, 5, 10]"
        :page-size="queryInfo.pagesize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total">
        <!-- layout控制分页显示内容 -->
      </el-pagination>
    </el-card>
    <!-- 添加用户区域 -->
    <!-- visible.sync控制对话框的显示与关闭 before-close为关闭对话框绑定了一个回调函数 -->
    <el-dialog
      title="添加用户"
      :visible.sync="dialogVisible"
      width="600px"
      :before-close="handleClose"
      @close="addFormClosed">
      <!-- close在对话框关闭时触发的事件与before-close有区别 -->
      <!-- 添加用户信息区域 -->
      <!-- ref属性是该组件的引用 -->
      <!-- label-width控制了表单内左侧文字离边缘的距离 -->
      <el-form :model="addForm" :rules="rules" ref="addFormRef" label-width="70px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="addForm.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input v-model="addForm.password"></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="addForm.email"></el-input>
        </el-form-item>
        <el-form-item label="电话" prop="mobile">
          <el-input v-model="addForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <!-- 底部区域 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="validateForm">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 修改用户信息区域 -->
    <el-dialog title="修改用户信息" :visible.sync="editDialogVisible" width="600px" :before-close="handleClose" @close="editFromReset">
      <el-form :model="editForm" :rules="rules" ref="editFormRef" label-width="70px">
        <el-form-item label="用户名">
          <el-input v-model="editForm.username" disabled></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="editForm.email"></el-input>
        </el-form-item>
        <el-form-item label="电话" prop="mobile">
          <el-input v-model="editForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editFromPut">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 分配角色对话框 -->
    <el-dialog title="分配角色" :visible.sync="setRolesDialogVisible" width="40%" @close="resetRolesListSelect">
      <div class="role-box">
        <p>当前的用户：{{userInfo.username}}</p>
        <p>当前的角色：{{userInfo.role_name}}</p>
        <p>分配新角色：
          <el-select v-model="value" placeholder="请选择">
            <el-option
              v-for="item in rolesList"
              :key="item.id"
              :label="item.roleName"
              :value="item.id">
            </el-option>
          </el-select>
        </p>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="setRolesDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveRoles">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: 'Users',
  data () {
    // 验证邮箱的自定义规则
    var checkEmail = (rule, value, callback) => {
      const regEmail = /^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*@[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*\.[a-z]{2,}$/
      if (regEmail.test(value)) {
        // 验证通过
        return callback()
      }
      // 验证未通过
      callback(new Error('请输入合法的邮箱'))
    }
    // 验证手机号的自定义规则
    var checkMobile = (rule, value, callback) => {
      const regMobile = /^1[0-9]{10}/
      if (regMobile.test(value)) {
        // 验证通过
        return callback()
      }
      // 验证未通过
      callback(new Error('请输入合法电话'))
    }
    return {
      // 用户信息请求数据
      queryInfo: {
        query: '',
        pagenum: 1,
        pagesize: 2
      },
      // 用户列表数据
      usersList: [],
      // 用户总数
      total: 0,
      // 添加用户对话框显示或隐藏参数
      dialogVisible: false,
      // 修改用户信息对话框显示或隐藏参数
      editDialogVisible: false,
      // 分配角色对话框显示状态
      setRolesDialogVisible: false,
      // 要删除用户的id
      removeUserId: '',
      // 执行分配角色操作的用户信息
      userInfo: {},
      // 角色列表 用于分配角色
      rolesList: [],
      // 用户添加信息
      addForm: {
        username: '',
        password: '',
        email: '',
        mobile: ''
      },
      // 使用id号查询到的用户信息 用于修改
      editForm: {},
      // 添加用户表单验证规则
      rules: {
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' },
          { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' },
          { min: 6, max: 15, message: '长度在 6 到 15 个字符', trigger: 'blur' }
        ],
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { validator: checkEmail, trigger: 'blur' }
        ],
        mobile: [
          { required: true, message: '请输入电话', trigger: 'blur' },
          { validator: checkMobile, trigger: 'blur' }
        ]
      },
      // 分配角色对话框中select选择器的value
      value: ''
    }
  },
  created () {
    this.getUsersList()
  },
  methods: {
    // 获取用户列表功能
    async getUsersList () {
      // params: this.queryInfo规定了输入参数
      const { data: res } = await this.$http.get('users', { params: this.queryInfo })
      if (res.meta.status !== 200) return this.$message.error('获取用户列表失败')
      // 获取用户列表成功后将数据挂载到vue中
      this.usersList = res.data.users
      this.total = res.data.total
      // console.log(res)
    },
    // 改变每页显示条数功能
    handleSizeChange (pagesize) {
      // console.log(pagesize)
      // 将更新的值赋给用户请求数据
      this.queryInfo.pagesize = pagesize
      // 重新发起一次请求
      this.getUsersList()
    },
    // 改变页数功能
    handleCurrentChange (current) {
      // console.log(current)
      // 将更新的值赋给用户请求数据
      this.queryInfo.pagenum = current
      // 重新发起一次请求
      this.getUsersList()
    },
    // 修改用户状态功能
    async userStateChange (user) {
      // console.log(user)
      // 向服务器发起请求修改用户状态
      const { data: res } = await this.$http.put(`users/${user.id}/state/${user.mg_state}`)
      // console.log(res)
      if (res.meta.status !== 200) {
        user.mg_state = !user.mg_state
        return this.$message.error('修改用户状态失败')
      }
      this.$message.success('更新用户状态成功')
    },
    // 关闭对话框前的回调函数
    handleClose (done) {
      this.$confirm('确认关闭？')
        .then(_ => {
          done()
        })
        .catch(_ => {})
    },
    // 关闭对话框时清除数据功能
    addFormClosed () {
      // 对话框关闭时 使用了引用调用了表单组件自带的方法重置表单
      this.$refs.addFormRef.resetFields()
    },
    // 在发起添加用户请求前对表单进行预验证
    validateForm () {
      // 引用vue组件并调用了组件内置的validate函数对表单进行预验证
      // 形参boolean是表单验证的结果 object是未通过的字段
      this.$refs.addFormRef.validate(async (boolean, object) => {
        // console.log(boolean, object)
        if (boolean) {
          // 如果验证通过则关闭对话框并向服务器发起请求
          this.dialogVisible = false
          const { data: res } = await this.$http.post('users', this.addForm)
          // console.log(res)
          if (res.meta.status === 201) {
            this.$message.success('添加用户成功')
            // 请求成功后更新一次用户列表数据
            return this.getUsersList()
          }
          // 请求未成功
          return this.$message.error('添加用户失败')
        }
        // 验证未通过
        this.$message.error('您的输入有误，请重新输入')
      })
    },
    // 修改用户数据功能
    async editDialog (id) {
      const { data: res } = await this.$http.get('users/' + id)
      // console.log(res)
      if (res.meta.status === 200) {
        // 显示修改用户数据的对话框
        this.editDialogVisible = true
        // 根据id查询用户信息成功
        this.editForm = res.data
      } else {
        this.$message.error('查询用户数据失败')
      }
    },
    // 关闭修改用户的对话框时重置表单
    editFromReset () {
      this.$refs.editFormRef.resetFields()
    },
    // 提交修改表单
    async editFromPut () {
      // 提交前验证表单
      this.$refs.editFormRef.validate(async (boolean, object) => {
        // console.log(boolean)
        if (boolean) {
          // 表单预验证通过
          const { data: res } = await this.$http.put(`users/${this.editForm.id}`, this.editForm)
          console.log(res)
          if (res.meta.status === 200) {
            // 提交成功
            this.editDialogVisible = false
            // 修改完成后重新从服务器获取一次数据
            return this.getUsersList()
          }
          // 提交失败
          return this.$message.error('修改失败')
        }
        // 表单预验证未通过
        this.$message.error('您的输入有误，请重新输入')
      })
    },
    // 删除按钮调用的方法
    open (id) {
      this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        // 确定删除操作
        // console.log(id)
        const { data: res } = await this.$http.delete('users/' + id)
        // console.log(res)
        if (res.meta.status === 200) {
          // 请求成功 刷新用户列表
          this.getUsersList()
          return this.$message.success('删除用户成功')
        }
        // 请求失败
        return this.$message.error('删除失败')
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    // 分配角色功能
    async setRoles (userInfo) {
      this.setRolesDialogVisible = true
      this.userInfo = userInfo
      // 获取角色列表
      const { data: res } = await this.$http.get('roles')
      if (res.meta.status !== 200) {
        return this.$message.error('获取角色列表失败')
      }
      this.rolesList = res.data
    },
    // 重置分配权限对话框的select选择器
    resetRolesListSelect () {
      this.value = ''
      this.userInfo = ''
    },
    // 分配角色发送请求
    async saveRoles () {
      // 未选择角色时value的值为空
      if (!this.value) {
        // 未改变select选择器选定的值
        return this.$message.error('请为用户选择一个角色')
      }
      const { data: res } = await this.$http.put(`users/${this.userInfo.id}/role`, { rid: this.value })
      if (res.meta.status === 200) {
        // 请求成功
        // 刷新用户列表
        this.getUsersList()
        this.setRolesDialogVisible = false
        return this.$message.success(res.meta.msg)
      }
      this.$message.error('分配角色失败')
    }
  }
}
</script>

<style lang="less" scoped>
.el-card {
  margin-top: 10px;
}
.el-table {
  margin-top: 10px;
}
.el-pagination {
  margin-top: 10px;
}
</style>
